/*
 * Copyright (c) 2020 Fraunhofer FOKUS and others. All rights reserved.
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contact: mosaic@fokus.fraunhofer.de
 */
package org.eclipse.mosaic.fed.sumo.traci.commands;

import org.eclipse.mosaic.fed.sumo.traci.AbstractTraciCommand;
import org.eclipse.mosaic.fed.sumo.traci.TraciCommandException;
import org.eclipse.mosaic.fed.sumo.traci.TraciConnection;
import org.eclipse.mosaic.fed.sumo.traci.TraciVersion;
import org.eclipse.mosaic.fed.sumo.traci.complex.Status;
import org.eclipse.mosaic.fed.sumo.traci.constants.CommandChangePolygonState;
import org.eclipse.mosaic.fed.sumo.traci.constants.TraciDatatypes;
import org.eclipse.mosaic.lib.geo.CartesianPoint;
import org.eclipse.mosaic.rti.api.InternalFederateException;

import java.awt.*;
import java.util.List;
import java.util.Random;

/**
 * This class adds a Polygon in the SUMO-GUI
 */
public class PolygonAdd extends AbstractTraciCommand<Void> {
    private static final int FILLED = 1;
    private static final int LAYER = 0;
    private static final String TYPE = "MOSAIC";

    private static final double LINE_WIDTH = 1;

    /**
     * Creates a new {@link PolygonAdd} traci command
     *
     * @see <a href="https://sumo.dlr.de/docs/TraCI/Change_Polygon_State.html">Change Polygon State</a>
     */
    public PolygonAdd(int n) {
        super(TraciVersion.LOWEST);

        // generate color randomly
        Random random = new Random();
        int r = random.nextInt(256);
        int g = random.nextInt(256);
        int b = random.nextInt(256);
        Color color =  new Color(r, g, b);

        TraciCommandWriterBuilder traciCommandWriterBuilder = write()
                .command(CommandChangePolygonState.COMMAND)
                .variable(CommandChangePolygonState.VAR_ADD)
                .writeStringParam() // POLY id
                .writeByte(TraciDatatypes.COMPOUND)
                .writeInt(6)
                .writeStringWithType(TYPE) // POLY type name
                .writeByte(TraciDatatypes.UBYTE_COLOR)
                .writeByte(color.getRed()) // red
                .writeByte(color.getGreen()) // green
                .writeByte(color.getBlue()) // blue
                .writeByte(color.getAlpha()) // alpha
                .writeByte(TraciDatatypes.UBYTE)
                .writeByte(FILLED) // filled
                .writeIntWithType(LAYER) // layer
                .writeByte(TraciDatatypes.UBYTE_POLYGON);

        if (n < 255) {
            traciCommandWriterBuilder
                    .writeByte(n);
        } else {
            traciCommandWriterBuilder
                    .writeByte(0)
                    .writeInt(n);
        }


        for (int i = 0; i < n;i++) {
              traciCommandWriterBuilder
                      .writeDoubleParam() // position x-i
                      .writeDoubleParam(); // position y-i
        }

        traciCommandWriterBuilder
                .writeDoubleWithType(LINE_WIDTH); // lineWidth
    }


    /**
     * Executes the command in order to add a new Polygon in the SUMO-GUI.
     */
    public void execute(TraciConnection traciCon, String polyId, List<CartesianPoint> vertices) throws TraciCommandException, InternalFederateException {
        int size = vertices.size();
        Object[] arguments = new Object[1 + size * 2];

        arguments[0] = polyId;

        for (int i = 0; i < size; i++) {
            arguments[1 + 2 * i] = vertices.get(i).getX();
            arguments[1 + 2 * i + 1] = vertices.get(i).getY();
        }


        super.execute(traciCon, arguments);
    }

    @Override
    protected Void constructResult(Status status, Object... objects) {
        return null;
    }
}
